####
#
# Copyright 2007 B. Chandler Carruth
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
####
#
# ./lib/rcons/tools/gcc/gcc_c_compiler_target.rb
#
# This file provides a C compiler target specialization.
#
####

require( 'rcons/tools/c_compiler_target' )

module RCons

  # Provides a representation for the Gcc C Compiler.
  #
  # Extends +CCompilerTarget+.
  class GccCCompilerTarget < CCompilerTarget
    # Set the rank of this compiler for class registration.
    RANK = 1
    # Register this compiler as a viable C compiler
    CCompilerTarget.register( GccCCompilerTarget )

    # Initialized the object.  Most of the work is handeled by parent
    # classes.
    #
    # Inputs:
    #
    # +build_env+:: an +Environment+.
    # +opts+:: a list of options.
    def initialize( build_env, opts = Hash.new() )
      # handle all the defaults for a target
      super( build_env, 'gcc', opts )

      @command = 'gcc'
    end

    # Examines the specified source file for any included files.
    #
    # Inputs:
    # +src_file+:: a path to the source file to examine.
    def included_files( src_file )
      files = []
      @build_env.exec_command( @command,
                               [ '-E', '-M', '-MG', "#{src_file}" ] ) do |p|
        for l in p
          l.chomp().chomp('\\').strip().scan( /(\\.|\S)+/ ) do
            files << $&.gsub( /\\(.)/, '\1' )
          end
        end
      end
      files.flatten!()

      # delete the "rule"
      files.delete_if() { |f| f =~ /:$/ }

      # delete the source file
      files.delete_if() { |f| f == src_file }

      # collect file names, fixing any without directories attached
      files.collect() do |f|
        if File.dirname(f) != '.'
          f
        else
          File.join( File.dirname(src_file), f )
        end
      end
    end

    # Provides an interface to compile source files.
    #
    # Inputs:
    # +target_file+:: the name of the compiled target files.
    # +src_files+:: a list of paths for all source files to be compiled.
    def compile( target_file, *src_files )
      @build_env.exec_command( @command,
                               [ '-o', "#{target_file}", '-c' ] + src_files )
    end

    # Provides an interface to link source files.
    #
    # Inputs:
    # +target_file+:: the name of the linked source files.
    # +src_files+:: a list of paths for all source files to be linked.
    def link( target_file, *src_files )
      @build_env.exec_command( @command,
                               [ '-o', "#{target_file}" ] + src_files )
    end

    # Provide dependency generation by finding the executable used for
    # the compile command, and dynamically adding it to dependencies.
    # The dynamic generation allows the executable to change location
    # freely. Changes to the executable (or to the location) will result
    # in a rebuild.
    #
    # Inputs:
    # +changed+:: The passed-around boolean for changes having been made.
    def build_pre_deps( changed )
      # create a file target for the executable, and add it to our deps
      if @command =~ /\//
        cmd_fn = @command
      else
        cmd_path = @build_env.path.detect() { |p| File.executable?( File.join( p.to_s(), @command.to_s() ) ) }
        cmd_fn = File.join( cmd_path.to_s(), @command.to_s() )
      end
      @command_file = FileTarget.new( @build_env, cmd_fn )
      add_pre_dep( @command_file )

      # now move on and process them
      super
    end

  end
end

